package com.snails.app.utils;

import android.content.Context;
import android.view.Gravity;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;

import com.snails.app.SnailsApp;
import com.snails.tool.display.DisplayUtils;
import com.snails.ui.toast.CToast;

/**
 * Created by lawrence on 2018/11/21.
 * <p>
 * 带有图片的Toast，图片在上，文字在下
 */

public class ToastUtil {
    // =====================================================================================
    // ---- 单利实现 ----
    // ==========================================
    private static volatile ToastUtil instance = null;
    private Context ctx;

    private ToastUtil(Context ctx) {
        this.ctx = ctx;
    }

    public static ToastUtil instance() {
        if (instance == null) {
            synchronized (ToastUtil.class) {
                if (instance == null)
                    instance = new ToastUtil(SnailsApp.instance().getCtx());
            }
        }
        return instance;
    }


    // =====================================================================================
    // ---- 成员变量 ----
    // ==========================================
    private CToast cToast = null;
    private Object lockObj = new Object(); // 模块锁


    // =====================================================================================
    // ---- 私有方法 ----
    // ==========================================

    /**
     * 参数校验
     *
     * @param builder
     */
    private void check(@NonNull Builder builder) {
        if (builder == null) {
            throw new RuntimeException("NullPoint：参数builder不能是null.");
        }
        if (builder.builder == null) {
            throw new RuntimeException("NullPoint：builder.mBuilder不能是null.");
        }
    }

    // =====================================================================================
    // ---- 对外方法 ----
    // ==========================================

    /**
     * 显示CToast
     *
     * @param builder
     */
    public void show(@NonNull Builder builder) {
        check(builder);
        synchronized (lockObj) {
            if (cToast != null && cToast.getView() != null) {
                cToast.setBuilder(builder.builder);
            } else {
                cToast = builder.builder.build(ctx);
            }
            cToast.setMargin(builder.horizontalMargin, builder.verticalMargin);
            cToast.setGravity(builder.gravity, builder.xOffset, builder.yOffset);
        }
        cToast.show();
    }

    /**
     * 显示CToast，并取消上一个Toast的显示
     *
     * @param builder
     */
    public void showLast(@NonNull Builder builder) {
        check(builder);
        synchronized (lockObj) {
            if (cToast != null) cToast.cancel();
            cToast = builder.builder.build(ctx);
            cToast.setMargin(builder.horizontalMargin, builder.verticalMargin);
            cToast.setGravity(builder.gravity, builder.xOffset, builder.yOffset);
        }
        cToast.show();
    }

    /**
     * toast图片文本
     *
     * @param drawableRes 显示的本地图片id
     * @param stringRes   显示文本本地id
     * @param duration    显示时长
     * @param gravity     显示位置
     */
    public void showImageText(@DrawableRes int drawableRes,
                              @StringRes int stringRes, int duration, int gravity) {
        final String message = ctx.getString(stringRes);
        showImageText(drawableRes, message, duration, gravity);
    }

    /**
     * toast文本
     *
     * @param stringRes 显示文本资源id
     * @param duration  显示时长
     * @param gravity   显示位置
     */
    public void showText(@StringRes int stringRes, int duration, int gravity) {
        showImageText(-1, stringRes, duration, gravity);
    }

    /**
     * toast文本
     *
     * @param message  显示文本
     * @param duration 显示时长
     * @param gravity  显示位置
     */
    public void showText(String message, int duration, int gravity) {
        showImageText(-1, message, duration, gravity);
    }

    /**
     * toast图片
     *
     * @param drawableRes 显示图片资源id
     * @param duration    显示时长
     * @param gravity     显示位置
     */
    public void showImage(@DrawableRes int drawableRes, int duration, int gravity) {
        showImageText(drawableRes, "", duration, gravity);
    }

    /**
     * toast图片文本
     *
     * @param drawableRes 显示的本地图片id
     * @param message     显示文本
     * @param duration    显示时长
     * @param gravity     显示位置
     */
    public void showImageText(@DrawableRes int drawableRes,
                              String message, int duration, int gravity) {
        final CToast.Builder cBuilder = new CToast.Builder();
        cBuilder.image(drawableRes).message(message).duration(duration);

        final Builder builder = new Builder();
        builder.builder(cBuilder).gravity(gravity);

        // 不居中的，默认给距顶和底一个间距
        if (gravity != Gravity.CENTER) {
            final int yOffset = DisplayUtils.instance().displayH() / 8;
            builder.yOffset(yOffset);
        }

        showLast(builder);
    }

    // =====================================================================================
    // ---- 构造器 ----
    // ==========================================
    public static class Builder {
        private CToast.Builder builder = null;
        private int gravity = Gravity.CENTER;
        private int xOffset = 0, yOffset = 0;
        private float horizontalMargin = 0;
        private float verticalMargin = 0;

        /**
         * 必需掉用
         *
         * @param builder 构造CToast必需参数
         */
        public Builder builder(@NonNull CToast.Builder builder) {
            this.builder = builder;
            return this;
        }

        public Builder gravity(int gravity) {
            this.gravity = gravity;
            return this;
        }

        public Builder xOffset(int xOffset) {
            this.xOffset = xOffset;
            return this;
        }

        public Builder yOffset(int yOffset) {
            this.yOffset = yOffset;
            return this;
        }

        public Builder horizontalMargin(float horizontalMargin) {
            this.horizontalMargin = horizontalMargin;
            return this;
        }

        public Builder verticalMargin(float verticalMargin) {
            this.verticalMargin = verticalMargin;
            return this;
        }

    }

}
